﻿using System;
using System.Collections.Generic;
using LocalizationUtils._3rdParty.AOTEasyAlphabetArabic;
using RTLTMPro;
using LocalizationUtils.Language;
using SCore.Core.LocalizationUtils.Utils;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;

namespace LocalizationUtils.Utils
{
    public static class LocalizationUtils
    {
        public const long ONE_DAY = 24 * 3600L;

        #region TMP

        static readonly FastStringBuilder finalText = new FastStringBuilder(RTLSupport.DefaultBufferSize);


        public static string GetFixedText(string input)
        {
            if (string.IsNullOrEmpty(input))
                return input;
            finalText.Clear();
            RTLSupport.FixRTL(input, finalText, false, true, true);
            finalText.Reverse();
            return finalText.ToString();
        }


        public static void SetColorGradient(this TextMeshProUGUI target, ColorMode colorMode, Color[] color)
        {
            switch (colorMode)
            {
                case ColorMode.Single:
                    target.colorGradient = new VertexGradient(color[0]);
                    break;
                case ColorMode.HorizontalGradient:
                    target.colorGradient = new VertexGradient(color[0], color[1], color[0], color[1]);
                    break;
                case ColorMode.VerticalGradient:
                    target.colorGradient = new VertexGradient(color[0], color[0], color[1], color[1]);
                    break;
                case ColorMode.FourCornersGradient:
                    target.colorGradient = new VertexGradient(color[0], color[1], color[2], color[3]);
                    break;
            }

            target.enableVertexGradient = true;
            target.havePropertiesChanged = true;
            target.SetVerticesDirty();
        }

        /// <summary>
        /// 详细时间参数，d :h  h:m m:s
        /// </summary>
        public static void SetTimeFormat(this LocalizationTMPText txtTime, long time, long formatKey = -1)
        {
            long days = (long)(time / 3600L / 24L);
            long hours = (long)(time / 3600L - days * 24L);
            long minutes = (long)(time - (hours * 3600L) - (days * 86400L)) / 60L;
            long seconds = (long)(time - (hours * 3600L) - (minutes * 60L) - (days * 86400L));

            if (days > 0)
            {
                if (formatKey != -1)
                {
                    txtTime.SetKeyWithParams(formatKey, Lang.GetFormat(800001002, days, hours));
                }
                else
                {
                    txtTime.SetKeyWithParams(formatKey != -1 ? formatKey : 800001002, days, hours);
                }
            }
            else if (hours > 0 && days == 0)
            {
                if (formatKey != -1)
                {
                    txtTime.SetKeyWithParams(formatKey, Lang.GetFormat(800001003, hours, minutes));
                }
                else
                {
                    txtTime.SetKeyWithParams(formatKey != -1 ? formatKey : 800001003, hours, minutes);
                }
            }
            else
            {
                if (formatKey != -1)
                {
                    txtTime.SetKeyWithParams(formatKey, Lang.GetFormat(800001004, minutes, seconds));
                }
                else
                {
                    txtTime.SetKeyWithParams(formatKey != -1 ? formatKey : 800001004, minutes, seconds);
                }
            }

            if (days == 0 && hours == 0 && minutes == 0 && seconds == 0)
            {
                txtTime.text = "";
            }
        }

        /// <summary>
        /// 详细时间参数，d:h:m  h:m:s 
        /// </summary>
        public static void SetDetailLongTime(this LocalizationTMPText text, long seconds)
        {
            if (seconds >= ONE_DAY)
            {
                long d = seconds / ONE_DAY;

                long remainderS = seconds % ONE_DAY;
                long h = remainderS / 3600L;

                remainderS = remainderS % 3600L;
                long m = remainderS / 60L;

                long s = remainderS % 60L;
                text.SetKeyWithParams(800001006, d.ToString("00"), h.ToString("00"), m.ToString("00"));
            }
            else
            {
                long h = seconds / 3600L;
                long remainder = seconds % 3600L;
                long m = remainder / 60L;
                long s = remainder % 60L;
                text.SetKeyWithParams(800001007, h.ToString("00"), m.ToString("00"), s.ToString("00"));
            }
        }

        public static void SetTimeFormatByOneParams(this LocalizationTMPText txtTime, long time, int formatKey = -1)
        {
            int days = (int)(time / 3600 / 24);
            int hours = (int)(time / 3600 - days * 24);
            int minutes = (int)(time - (hours * 3600) - (days * 86400)) / 60;
            int seconds = (int)(time - (hours * 3600) - (minutes * 60) - (days * 86400));

            if (days > 0)
            {
                txtTime.SetKeyWithParams(formatKey != -1 ? formatKey : 1800001008, days);
            }
            else if (hours > 0 && days == 0)
            {
                txtTime.SetKeyWithParams(formatKey != -1 ? formatKey : 1800001009, hours);
            }
            else
            {
                txtTime.SetKeyWithParams(formatKey != -1 ? formatKey : 1800001010, minutes);
            }

            if (days == 0 && hours == 0 && minutes == 0 && seconds == 0)
            {
                txtTime.text = "";
            }
        }


        /// <summary>
        /// 详细时间参数，年/月/日
        /// </summary>
        public static void SetTimeFormatType1(this LocalizationTMPText txtTime, long time)
        {
            DateTime dateTime = DateTimeOffset.FromUnixTimeSeconds(time).DateTime;
            txtTime.SetKeyWithParams(800001015, dateTime.Year, dateTime.Month, dateTime.Day);
        }


        public static void SetColor(this TextMeshProUGUI target, Color color)
        {
            target.color = new Color(color.r, color.g, color.b);
        }

        public static void SetUIText(this TextMesh target, string content)
        {
            if (LocalizationManager.CurrSystemLanguage == LocalizationManager.CustomSystemLanguage.Arabic)
            {
                target.text = MirrorCharacters(EasyArabicCore.CorrectString(content));
            }
            else
            {
                target.text = content;
            }
        }

        #endregion

        #region UGUI

        private static readonly Dictionary<char, char> MirroredCharsMap = new Dictionary<char, char>()
        {
            ['('] = ')',
            [')'] = '(',
            ['»'] = '«',
            ['«'] = '»',
            ['['] = ']',
            [']'] = '[',
            ['{'] = '}',
            ['}'] = '{',
            ['「'] = '」',
            ['」'] = '「',
        };

        public static string MirrorCharacters(string input)
        {
            char[] resultArray = new char[input.Length];

            for (int i = 0; i < input.Length; i++)
            {
                char currentChar = input[i];

                if (MirroredCharsMap.ContainsKey(currentChar))
                {
                    resultArray[i] = MirroredCharsMap[currentChar];
                }
                else
                {
                    resultArray[i] = currentChar;
                }
            }

            return new string(resultArray);
        }


        public static bool HasArabic(string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            int strLength = str.Length;
            for (var i = 0; i < strLength; i++)
            {
                char c = str[i];
                if (isArabic(c))
                {
                    return true;
                }
            }

            return false;
        }

        public static bool isArabic(char c)
        {
            if (c >= 0x600 && c <= 0x6ff) return true;
            if (c >= 0x750 && c <= 0x77f) return true;
            if (c >= 0xfb50 && c <= 0xfc3f) return true;
            if (c >= 0xfe70 && c <= 0xfefc) return true;
            return false;
        }

        public static void SetUIText(this Text text, string content)
        {
            if (LocalizationManager.CurrSystemLanguage == LocalizationManager.CustomSystemLanguage.Arabic)
            {
                //多行
                var aText = text.GetComponent<ArabicMultiLineText>();
                if (aText != null)
                {
                    aText.enabled = true;
                    aText.Text = content;
                    aText.Start();
                    aText.Update();
                }
                else
                {
                    text.text =
                        MirrorCharacters(EasyArabicCore.CorrectString(content));
                }
            }
            else
            {
                if (text.GetComponent<ArabicMultiLineText>() != null)
                {
                    text.GetComponent<ArabicMultiLineText>().enabled = false;
                }

                text.text = content;
            }
        }

        public static void SetArab(this Text text, bool _arabicMultiLine = false)
        {
            if (LocalizationManager.CurrSystemLanguage == LocalizationManager.CustomSystemLanguage.Arabic)
            {
                AdjustArabRight(text);
                if (_arabicMultiLine)
                    text.AddComponent<ArabicMultiLineText>();
            }
        }

        public static void AdjustArabRight(this Text text)
        {
            if (text.alignment == TextAnchor.LowerLeft)
            {
                text.alignment = TextAnchor.LowerRight;
            }
            else if (text.alignment == TextAnchor.MiddleLeft)
            {
                text.alignment = TextAnchor.MiddleRight;
            }
            else if (text.alignment == TextAnchor.UpperLeft)
            {
                text.alignment = TextAnchor.UpperRight;
            }
        }

        #endregion

        static void AAA()
        {
            long key = 11;
            LocalizationUGUIText _txt = null;
            _txt.SetKey(key);
            LocalizationTMPText _tmp = null;
            _tmp.SetKey(key);
        }

        public static void SetKey(this ILocalization localization, long key)
        {
            localization.key = key;
            localization.text = Lang.Get(key);
        }


        public static void SetKeyWithParams(this ILocalization localization, long key, params object[] args)
        {
            localization.key = key;
            localization.text = Lang.GetFormat(key, args);
        }

        //object[] args = { 0, "apple", 1, 1001, 0, "banana", 1, 1002, 0, "orange" };
        public static void SetKeyWithParamsByType(this ILocalization localization, long key, params object[] args)
        {
            object[] newArgs = new object[args.Length / 2];
            int newArgIndex = 0;

            for (int i = 0; i < args.Length; ++i)
            {
                if (i % 2 == 0)
                {
                    int paramsType = Convert.ToInt32(args[i]);
                    if (paramsType == 0)
                    {
                        newArgs[newArgIndex] = args[i + 1];
                    }
                    else if (paramsType == 1)
                    {
                        int tmpKey = Convert.ToInt32(args[i + 1]);
                        var text = Lang.Get(tmpKey);
                        newArgs[newArgIndex] = text;
                    }

                    newArgIndex++;
                }
            }

            SetKeyWithParams(localization, key, newArgs);
        }

        public static void SetParams(this ILocalization localization, params object[] args)
        {
            SetKeyWithParams(localization, localization.key, args);
        }

        public static void SetParamsByType(this ILocalization localization, params object[] args)
        {
            SetKeyWithParamsByType(localization, localization.key, args);
        }
    }
}